package com.jswl.training.springjpa.frame;

import com.jswl.training.springjpa.util.ByteUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

import java.util.ArrayList;

/**
 * 导航7B协议帧编码器类
 * <p>
 * 将包装好的数据帧（Nav7BFrame）转换为 二进制待发送数据（ByteBuf）
 */
public class Nav7BFramePacketEncoder {



    //region Private Methods

    /**
     * @param frame
     * @return
     */
    private ByteBuf convertFrameBodyToByteBuf(Nav7BFrame frame) {

        ByteBuf buff = assembleFrameWithRefactor(frame);

        return buff;
    }

    /**
     * @param frame
     * @return
     */
    private ByteBuf assembleFrameWithRefactor(Nav7BFrame frame) {
        byte[] refactoredBytes = getRefactoredBytes(frame);
        int bufferCapacity = InternalShared.FRAME_SHELL_SIZE + refactoredBytes.length;
        ByteBuf byteBuf = Unpooled.buffer(bufferCapacity, bufferCapacity);
        //帧头
        byteBuf.writeBytes(InternalShared.FRAME_HEADER_BYTES);
        //信源
        byteBuf.writeByte((byte) frame.getSourcePrimaryId());
        byteBuf.writeByte((byte) frame.getSourceSecondaryId());
        //信宿
        byteBuf.writeByte((byte) frame.getTargetPrimaryId());
        byteBuf.writeByte((byte) frame.getTargetSecondaryId());
        //信息类型
        byteBuf.writeByte(frame.getInfoType());
        //信息长度 + 数据类型 + 数据位长度 + 数据内容
        byteBuf.writeBytes(refactoredBytes);
        //校验
        byteBuf.writeByte(InternalShared.computeCheckSum(frame));
        //帧尾
        byteBuf.writeByte(InternalShared.FRAME_FINISH_FLAG);

        return byteBuf;
    }

    /**
     * 对信息长度+数据类型+数据位长度+数据内容进行7B重复检测和重构
     *
     * @param frame 待处理数据帧
     * @return 重构后的数据
     */
    private byte[] getRefactoredBytes(Nav7BFrame frame) {
        ArrayList<Byte> bytes = new ArrayList<>();
        //信息长度
        appendShortBytes(bytes, frame.getInfoLength());
        //数据类型
        appendShortBytes(bytes, frame.getDataType());
        //数据位长度
        appendShortBytes(bytes, frame.getBitLength());
        //数据内容
        ByteBuf buff = frame.getDataContent();
        buff.readerIndex(0);
        while (buff.readableBytes() > 0) {
            bytes.add(buff.readByte());
        }

        //将帧数据转换为数组形式并返回结果
        byte[] result = new byte[bytes.size()];
        for (int i = 0; i < result.length; ++i) {
            result[i] = bytes.get(i);
        }
        return result;
    }


    /**
     * @param bytes
     * @param value
     */
    private void appendShortBytes(ArrayList<Byte> bytes, int value) {
        byte[] infoLengthBytes = ByteUtils.unsignedShortToBytesLE(value);
        bytes.add(infoLengthBytes[0]);
        bytes.add(infoLengthBytes[1]);
    }



    //endregion
}
